#include "../../inc/protocol.h"
#include "../../inc/my_sqlite3.h"
#include "../../inc/server.h"
int server_main_loop(int servfd)
{
	int datafd = -1;
	pthread_t tid;
	int ret = 0;
	struct threadarg* parg = NULL;
	sqlite3 * pdb =NULL; 
	pdb = create_db_engine("./data.db");
	while(1)
        {
                datafd = accept(servfd,NULL,NULL);
		parg = malloc(sizeof(struct threadarg));
		parg->datafd = datafd;
		parg->pdb = pdb;
                if(datafd < 0)
                {
                        if(errno == EINTR)
                        {
                                continue;
                        }
                        else
                        {
                                printf("accept error\n");
                                break;
                        }
                }
                else
                {
			ret = pthread_create(&tid,NULL,handle_client,(void*)parg);
			if(ret)
			{
				free(parg);
				parg = NULL;
				close(datafd);
				datafd = -1;
			}
                }
        }
	destory_db_engine(pdb);
	pdb = NULL;
	return 0;
}

void * handle_client(void *arg) {
    struct threadarg *parg = (struct threadarg*)arg;
    int datafd = parg->datafd;
    sqlite3* pdb = parg->pdb;
    char username[NAME_LEN] = "";
    free(parg);
    parg = NULL;
    int ret = 0;
    int exitflag = 0;
    struct DictOLPDU* reqpdu = NULL;

    pthread_detach(pthread_self());

    while (1) {
        reqpdu = RecvPDU(datafd);
        if (NULL == reqpdu) {
            printf("recv reqpdu from client failed\n");
            break;
        }

        switch (reqpdu->type) {
            case REG_REQ:
                ret = Register(datafd, pdb, reqpdu);
                if (ret < 0) {
                    exitflag = 1;
                }
                break;
            case LOGIN_REQ:
                ret = login(datafd, pdb, reqpdu);
                if (ret < 0) {
                    exitflag = 1;
                } else if (ret == 0) {
                    // 登录成功，执行其他操作
                    strncpy(username, reqpdu->buf, sizeof(username) - 1); // 保存用户名
                    break;
                }
                DestroyDictOLPDU(reqpdu);
                reqpdu = NULL;
                break;
            case QUERYWORD_REQ:
                ret = HandleQueryWord(datafd, pdb, reqpdu, username);
                if (ret < 0) {
                    exitflag = 1;
                }
                break;
            case HISTORY_REQ:
                ret = HandleQueryHistory(datafd, pdb, reqpdu, username);
                if (ret < 0) {
                    exitflag = 1;
                }
                break;
            default:
                break;
        }
        if (exitflag) {
            break;
        }
    }
    update_login_flag(pdb,username,0);
    close(datafd);
    datafd = -1;

    return NULL;
}


int Register (int datafd,struct sqlite3 *pdb,struct DictOLPDU * reqpdu)
{
	int ret;
	struct  DictOLPDU *rsppdu = NULL;
	char name[20] = "";
	char password[20] = "";
	strncpy(name,reqpdu->buf,NAME_LEN-1);
	strncpy(password,reqpdu->buf+NAME_LEN,PASS_LEN-1);
	ret=register_new_user(pdb,name,password);
	rsppdu = CreateRegisterRSPPDU(ret);
	DestroyDictOLPDU(reqpdu);
	reqpdu = NULL;
	if(rsppdu == NULL)
	{
	    return 1;    
	}
	ret =SendPDU(datafd,rsppdu);
	DestroyDictOLPDU(rsppdu);
	rsppdu = NULL;
	if(ret)
	{
		return -1;
	}

	return 0;
}
int login (int datafd,struct sqlite3 *pdb,struct DictOLPDU * reqpdu)
{
	int ret;
	struct  DictOLPDU *rsppdu = NULL;
	char name[20] = "";
	char password[20] = "";
	strncpy(name,reqpdu->buf,NAME_LEN-1);
	strncpy(password,reqpdu->buf+NAME_LEN,PASS_LEN-1);
	ret=user_login(pdb,name,password);
	rsppdu = CreateLoginRSPPDU(ret);
	DestroyDictOLPDU(reqpdu);
	reqpdu = NULL;
	if(rsppdu == NULL)
	{
	    return -1;    
	}
	ret =SendPDU(datafd,rsppdu);
	DestroyDictOLPDU(rsppdu);
	rsppdu = NULL;
	if(ret)
	{
	    printf("error\n");
		return -1;
	}

	return 0;
}
int HandleQueryWord (int datafd,struct sqlite3 *pdb,struct DictOLPDU * reqpdu,char *username)
{
	int ret;
	struct  DictOLPDU *rsppdu = NULL;
	rsppdu = QueryWordFromFile(reqpdu->buf);
	ret=insert_or_update_history_record(pdb,username,reqpdu->buf);
	DestroyDictOLPDU(reqpdu);
	reqpdu = NULL;
	if(rsppdu == NULL)
	{
	    return 1;    
	}
	ret =SendPDU(datafd,rsppdu);
	DestroyDictOLPDU(rsppdu);
	rsppdu = NULL;
	if(ret)
	{
		return -1;
	}
	return 0;
}

int HandleQueryHistory (int datafd,struct sqlite3 *pdb,struct DictOLPDU * reqpdu,char*username)
{
     struct DictOLPDU *rsppdu = NULL;
    int ret = 0;
    char *p = NULL;

    // 调用GetUserAllHistoryRecords函数获取用户的所有历史记录
    p = get_all_history_record_by_username(pdb, username);

    // 使用获取到的历史记录创建历史记录响应PDU
    rsppdu = CreateHistoryRSPPDU(p);
    free(p);
    p = NULL;
    DestroyDictOLPDU(reqpdu);
    reqpdu = NULL;
    if(rsppdu == NULL)
    {
	   return -1;
    }

    // 发送到客户端
    ret = SendPDU(datafd,rsppdu);
	
    DestroyDictOLPDU(rsppdu);
    rsppdu = NULL;
    if(ret)
    {
	  return -2;
    }
    return 1;   
}



int create_server_socket(const char *ip,unsigned short port,int listennum)
{
	int servfd = -1;
	struct sockaddr_in servaddr;
	int ret = 0;

	servfd = socket(AF_INET,SOCK_STREAM,0);

        bzero(&servaddr,sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        servaddr.sin_port = htons(port);
        if(!inet_aton(ip,&servaddr.sin_addr))
	{
		printf("The IP-Address:%s is invalid\n",ip);
		close(servfd);
		servfd = -1;
		return -1;
	}

        /*为socket函数创建的用于服务端通讯的引擎对象指定IP地址和端口号*/
        ret = bind(servfd,(struct sockaddr *)&servaddr,sizeof(servaddr));

        /*将socket函数创建的主动socket变更为被动socket*/
        ret += listen(servfd,listennum);
        if(ret)
        {
                printf("In server,bind or listen failed\n");
                close(servfd);
                servfd = -1;
                return -2;
        }

	return servfd;
}
/*从pf代表的文本文件中读出一整行，位置指示器指示到下一行*/
char *MyReadLineFromTxt(FILE *pf,int *linelen)
{
    int len = 0;
    char *p = 0;
    char *pret = 0;
    long cur = 0;
    int ret = 0;

    if(NULL == pf)
    {
        printf("Input Param is invalid \n");/*相等于调用printf*/
        return NULL;
    }
    
    if(linelen != NULL)
    {
        *linelen = 0;
    }

    cur = ftell(pf);
    
    ret = fgetc(pf);
    while(ret >= 0 && ret != '\n')
    {
			len++;
    	ret = fgetc(pf);
    }
    if(ret == '\n')
    {
      len++;
    }

    if(len <= 0)
    {
			return NULL;
    }

    fseek(pf,cur,SEEK_SET);

    p =(char *)malloc(len+1);
    if(NULL == p)
    {
        printf("malloc failed\n");
				return NULL;
    }
    memset(p,0,len+1);

    pret = fgets(p,len+1,pf);
    if(pret != p)
    {
        printf("fgets failed\n");
        free(p);
        return NULL;
    }

    if(p[len-1]=='\n')
    {
        p[len-1] = '\0';
				len--;
    }
    if(p[len-1]=='\r')
    {
        p[len-1] = '\0';
				len--;
    }

    if(linelen != NULL)
    {
        *linelen = len;
    }
    return p;	
}

/*从dict.txt文件中查找一个单词的英文释义，并创建好查词回应PDU*/
struct DictOLPDU * QueryWordFromFile(char *word)
{
		FILE *fp = NULL;
		char *pline = NULL;
		char *p = NULL;
		int len;
		int result;
		struct DictOLPDU *pstRspPDU = NULL;

    len = strlen(word);
    if ((fp = fopen("dict.txt", "r")) == NULL)
    {
			printf("fopen dict.txt failed\n");		
			return NULL;
    }

    printf("query word is %s\n",word);
		pline = MyReadLineFromTxt(fp,NULL);
    while (pline != NULL)
    {
        result = strncmp(word, pline, len);
	if(0==result)
	{
	    break;
	}
	else
	{
	    free(pline);
	    pline = NULL;
	    pline = MyReadLineFromTxt(fp,NULL);
	}
    }
		fclose(fp);
		fp = NULL;

		if(pline != NULL)
		{
			p = pline + len;
			while(*p == ' ') 
			{
				p++;
			}
			pstRspPDU = CreateQueryWordRSPPDU(p);
			free(pline);
			pline = NULL;
			p = NULL;
		}
		else
		{
			pstRspPDU = CreateQueryWordRSPPDU(QUERY_WORD_ERR_STR);
		}

		return pstRspPDU;	
}


